<?php

namespace app\common\model;

use app\common\facade\CategoryFacade;
use InvalidArgumentException;

class SitemapModel
{
    private $_xml;
    public $mode;

    public function __construct($mode = '')
    {
        $this->mode = $mode;
    }
    public function init()
    {
        if ($this->_xml != null) return;
        if ($this->mode == 'index') {
            $this->_xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><sitemapindex namespace="http://www.sitemaps.org/schemas/sitemap/0.9"></sitemapindex>');
        } else {
            $this->_xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><urlset namespace="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
        }
    }

    /**
     * 生成sitemap
     * @param int $page 
     * @return void 
     * @throws InvalidArgumentException 
     */
    public function create($page = 0)
    {
        $this->init();
        if ($page < 1) {
            $this->createIndexUrl($this->_xml->addChild('url'));
            $this->writeChannel();
        } else {
            $this->writeArticle($page);
        }
    }

    public function createAll()
    {
        $this->create();
        $page = 1;
        while ($this->writeArticle($page) > 0) {
            $page++;
        }
    }

    /**
     * todo 创建索引文件
     * @return void 
     */
    public function createIndex()
    {
        $this->mode = 'index';
        $this->init();

        $lastArticle = ArticleModel::where('status', 1)->where('is_hidden', 0)->order('create_time desc')->find();
        if (empty($lastArticle)) {
            $lastArticle = ['create_time' => strtotime('yestoday')];
        }

        $map = $this->_xml->addChild('sitemap');
        $map->addChild('loc', url('index/index/sitemap', ['page' => 0], 'xml', true));
        $map->addChild('lastmod', date('Y-m-d', $lastArticle['create_time']));

        $totalCount = ArticleModel::where('status', 1)->where('is_hidden', 0)->count();
        $totalPage = ceil($totalCount / 100);
        for ($i = 1; $i <= $totalPage; $i++) {
            $lastArticle = ArticleModel::where('status', 1)->where('is_hidden', 0)->order('create_time desc')->limit(($i - 1) * 100, 1)->find();
            $map = $this->_xml->addChild('sitemap');
            $map->addChild('loc', url('index/index/sitemap', ['page' => $i], 'xml', true));
            $map->addChild('lastmod', date('Y-m-d', $lastArticle['create_time']));
        }
    }

    /**
     * 创建首页链接属性
     * @param SimpleXMLElement $url 
     * @return void 
     */
    private function createIndexUrl($url)
    {
        $lastArticle = ArticleModel::where('status', 1)->order('create_time desc')->find();
        if (empty($lastArticle)) {
            $lastArticle = ['create_time' => strtotime('yestoday')];
        }
        $url->addChild('loc', url('/', '', true, true));
        $url->addChild('lastmod', date('Y-m-d', $lastArticle['create_time']));
        $url->addChild('changefreq', 'weekly');
        $url->addChild('priority', '1');
    }

    /**
     * 写入频道链接
     * @return void 
     * @throws InvalidArgumentException 
     */
    public function writeChannel()
    {
        $categories = CategoryFacade::getSubCategory(0);
        foreach ($categories as $channel) {
            $this->createCateUrl($this->_xml->addChild('url'), $channel, $channel['channel_mode']);
            $this->writeCategory($channel);
        }
    }

    /**
     * 写入分类链接
     * @param mixed $channel 
     * @return void 
     * @throws InvalidArgumentException 
     */
    public function writeCategory($channel)
    {
        $categories = CategoryFacade::getSubCategory($channel['id']);
        foreach ($categories as $cate) {
            $this->createCateUrl($this->_xml->addChild('url'), $cate, $channel['channel_mode']);
            $this->writeCategory($cate);
        }
    }

    /**
     * 创建频道和分类的链接属性
     * @param SimpleXMLElement $url 
     * @param Model $cate 
     * @return void 
     */
    private function createCateUrl($url, $cate, $channel_mode, $page = 0)
    {
        $lastArticle = ArticleModel::where('status', 1)->whereIn('cate_id', CategoryFacade::getSubCateIds($cate['id'], true))->order('create_time desc')->find();
        if (empty($lastArticle)) {
            $lastArticle = ['create_time' => strtotime('yestoday')];
        }
        $pagecount = 0;
        if ($channel_mode == 2 && $cate['pid'] == 0) {
            $url->addChild('priority', '0.9');
            $url->addChild('loc', indexurl($cate['name'], true, true));
        } else {
            if ($cate['pid'] == 0) {
                $url->addChild('priority', '0.8');
                $url->addChild('loc', listurl($cate['name'], '', true, true) . ($page > 0 ? "/$page" : ''));
            } else {
                $url->addChild('priority', '0.7');
                $url->addChild('loc', listurl($cate['name'], '', true, true) . ($page > 0 ? "/$page" : ''));
            }
            if ($page < 1 && $channel_mode != 1) {
                $totalCount = ArticleModel::where('status', 1)->whereIn('cate_id', CategoryFacade::getSubCateIds($cate['id'], true, true))->count();
                $channel = $cate['pid'] == 0 ? $cate : CategoryFacade::getTopCategory($cate['id']);
                $pagesize = empty($channel['pagesize']) ? 12 : $channel['pagesize'];
                $pagecount = ceil($totalCount / $pagesize);
            }
        }
        $url->addChild('lastmod', date('Y-m-d', $lastArticle['create_time']));
        $url->addChild('changefreq', 'monthly');
        if ($pagecount > 0) {
            for ($i = 2; $i <= $pagecount; $i++) {
                $this->createCateUrl($this->_xml->addChild('url'), $cate, $channel_mode, $i);
            }
        }
    }

    /**
     * 写入文章链接
     * @return int 
     */
    public function writeArticle($page = 1)
    {
        $lists = ArticleModel::getInstance()->tagList(['page' => $page, 'pagesize' => 100]);
        foreach ($lists as $item) {
            $this->createUrl($this->_xml->addChild('url'), $item);
        }
        return empty($lists) ? 0 : count($lists);
    }

    /**
     * 创建文章的链接属性
     * @param SimpleXMLElement $url 
     * @param Model $article 
     * @return void 
     */
    private function createUrl($url, $article)
    {
        if (($article['type'] & 2) == 2) {
            $url->addChild('priority', '0.5');
        }
        $url->addChild('loc', viewurl($article, '', true, true));
        $url->addChild('lastmod', date('Y-m-d', $article['update_time']));
        $url->addChild('changefreq', 'never');
    }

    public function writeToFile($file)
    {
        return $this->_xml->asXML($file);
    }

    public function getXml()
    {
        return $this->_xml->asXML();
    }
}
